package com.algorithm.shell;/*
 *@Author:DOWN
 *@Date:2022/3/15 15:57
 *@Comment:希尔排序
 */

public class ShellSort {
    private ShellSort() {
    }

    /**
     * 传统希尔
     *
     * @param data 元素组
     * @param <E>  泛型
     */
    public static <E extends Comparable<E>> void sort(E[] data) {
        int h = data.length / 2;
        while (h >= 1) {
            for (int start = 0; start < h; start++) {
                //对 data[start,start+h,start+2h······],的区间内做插入排序
                for (int i = start + h; i < data.length; i += h) {
                    E t = data[i];
                    int j;
                    //从后往前 做插入排序 ，直至将后面的元素 移动到 正确的位置
                    for (j = i; j - h >= 0 && t.compareTo(data[j]) < 0; j -= h) {
                        data[j] = data[j - h];
                    }
                    data[j] = t;
                }
            }
            h /= 2;
        }
    }

    /**
     * 传统希尔 减少一层 循环
     *
     * @param data 元素组
     * @param <E>  泛型
     */
    public static <E extends Comparable<E>> void sort2(E[] data) {
        int h = data.length / 2;
        while (h >= 1) {
            //按下标顺序 做间隔排序
            for (int i = h; i < data.length; i ++) {
                E t = data[i];
                int j;
                //从后往前 做插入排序 ，直至将后面的元素 移动到 正确的位置
                for (j = i; j - h >= 0 && t.compareTo(data[j]) < 0; j -= h) {
                    data[j] = data[j - h];
                }
                data[j] = t;
            }

            h /= 2;
        }
    }

    /**
     * 步长序列  指数级间隔
     *
     * @param data 元素组
     * @param <E>  泛型
     */
    public static <E extends Comparable<E>> void sort3(E[] data) {
        int h = 1;
        while (h < data.length) {
            h = h * 3 + 1;
        }
        while (h >= 1) {
            //对 data[h,n],的区间内做插入排序
            for (int i = h; i < data.length; i += h) {
                E t = data[i];
                int j;
                //从后往前 做插入排序 ，直至将后面的元素 移动到 正确的位置
                for (j = i; j - h >= 0 && t.compareTo(data[j - h]) < 0; j -= h) {
                    data[j] = data[j - h];
                }
                data[j] = t;
            }
            h /= 3;
        }
    }
}
